﻿using System;
using System.Linq;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using CompactFramework.Utilities.Localization;
using System.Net;

using TripLOAMobile.InternalEntities;
using TripLOAMobile.InternalEntities.ExtensionsMethods;

namespace TripLOAMobile
{
    public delegate void delegateDispose();

    /// <summary>
    /// This form is used to create a new travel
    /// </summary>
    public partial class InsertTravel : LocalizedForm
    {
        public delegateDispose DelegateDispose;
        private InsertTravelInfo formStatus;

        private AnimationControl animation;

        private bool gpsDepEvent = false;
        private bool gpsDestEvent = false;
        private bool first = false;
        private object controlSender;

        private List<WS_SoapLogin.VehicleInfo> listOfVehicles;
        private string status;

        /// <summary>
        /// Initializes a new instance of the <see cref="InsertTravel"/> class.
        /// </summary>
        public InsertTravel()
        {
            InitializeComponent();
            delta = lblDest.Top - lblDpt.Top; //Used on keyboad showing
            this.AddMenusToDictionary();
            UpdateResources();
            #region creation of the control for the animation
            animation = new AnimationControl();
            int x = this.Width / 2 - animation.Width / 2;
            int y = this.Height / 2 - animation.Height / 2;
            animation.Location = new Point(x, y);
            this.Controls.Add(animation);
            animation.BringToFront();
            #endregion
            formStatus = new InsertTravelInfo();
            controlSender = null;
            DelegateDispose = new delegateDispose(this.Dispose);
            #region vehicles
            listOfVehicles = Welcome.rrp.GetListOfVehicles();
            if(listOfVehicles!=null)
                for (int i = 0; i < listOfVehicles.Count; i++)
                    comboVehicle.Items.Add(listOfVehicles[i].VehicleClass+" ("+listOfVehicles[i].Model+")");
            comboVehicle.SelectedIndexChanged += new System.EventHandler(comboVehicle_SelectedIndexChanged);
            comboVehicle.SelectedIndex = comboVehicle.Items.Count > 8 ? 8 : 0; //Di default vehicle becomes "Utilitaria" instead of "Nave"
            #endregion
        }

        #region start/stop animation
        delegate void animationDel();

        /// <summary>
        /// Stops the animation
        /// </summary>
        private void stopAnimation()
        {
            foreach (Control c in this.Controls)
            {
                c.Enabled = true;
            }
            this.menuLeft.Enabled = true;
            this.menuRight.Enabled = true;
            this.animation.StopAnimation();
            this.AutoScroll = true;
        }

        /// <summary>
        /// Starts the animation
        /// </summary>
        private void startAnimation()
        {
            foreach (Control c in this.Controls)
            {
                c.Enabled = false;
            }
            this.menuLeft.Enabled = false;
            this.menuRight.Enabled = false;
            this.animation.StartAnimation();
            this.AutoScroll = false;
        }
        #endregion

        /// <summary>
        /// Handles the SelectedIndexChanged event of the comboVehicle control.
        /// If the selected vehicle changes, the number of seats available also changes
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void comboVehicle_SelectedIndexChanged(object sender, System.EventArgs e)
        {
            if ((comboVehicle.SelectedIndex == -1) || (comboVehicle.SelectedIndex>=this.listOfVehicles.Count))
            {
                this.numSeats.Enabled = false;
                this.numSeats.Minimum = 0;
                this.numSeats.Maximum = 0;
            }
            else{
                this.numSeats.Enabled = (this.listOfVehicles[comboVehicle.SelectedIndex].MaxSeatNumber == 0) ? false : true;
                this.numSeats.Minimum = 1;
                this.numSeats.Value = 1 ;
                this.numSeats.Maximum = this.listOfVehicles[comboVehicle.SelectedIndex].MaxSeatNumber;
            }
        }

        /// <summary>
        /// The subclasses of the LocalizedForm should override this method and use this method to
        /// associate all menu items with custom names with the help of <see cref="AddMenuToDictionary"/> method.
        /// </summary>
        protected override void AddMenusToDictionary()
        {
            this.AddMenuToDictionary(this.menuLeft, "menuLeft");
            this.AddMenuToDictionary(this.menuRight, "menuRight");
            this.AddMenuToDictionary(this.publishMenuItem, "menuPublish");
            this.AddMenuToDictionary(this.draftMenuItem, "menuDraft");
        }

        /// <summary>
        /// When the form is closed, gps methods must be
        /// removed from the handlers
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void _Closed(object sender, System.EventArgs e)
        {
            if (gpsDepEvent)
            {
                Welcome.gps.DeviceStateChanged -= gps_DepDeviceStateChanged;
                Welcome.gps.LocationChanged -= gps_DepLocationChanged;
                gpsDepEvent = false;
            }
            if (gpsDestEvent)
            {
                Welcome.gps.DeviceStateChanged -= gps_DestDeviceStateChanged;
                Welcome.gps.LocationChanged -= gps_DestLocationChanged;
            }
        }

        private void menuBack_Click(object sender, EventArgs e)
        {
            Welcome.formBuffer.Close();
        }

        #region ResponseHandling
        /// <summary>
        /// This method is invoked from RemoteResourceProvider when the communication is terminated
        /// </summary>
        /// <param name="e">The <see cref="TripLOAMobile.RemoteResourceProvider.InsertTravelResponseEventArgs"/> instance containing the event data.</param>
        void rrp_InsertTravelRensponse(RemoteResourceProvider.InsertTravelResponseEventArgs e)
        {
            this.stopAnimation();
            this.status = e.Status;
            if (e.Status == RemoteResourceProvider.okStatus)
            {
                int newId = e.InsertedTripID;
                MessageBox.Show(ResourceManager.Instance.GetString("InsertOk"));
                Welcome.formBuffer.Close();
            }
            else
            {
                //Handle somehow (o authcode sbagliato, o problemi di connessione)
                MessageBox.Show(ResourceManager.Instance.GetString("InsertFail")+" ("+e.Status+")");
            }
        }
        #endregion

        /// <summary>
        /// Raises the <see cref="E:System.Windows.Forms.Control.Paint"/> event.
        /// </summary>
        /// <param name="e">A <see cref="T:System.Windows.Forms.PaintEventArgs"/> that contains the event data.</param>
        protected override void OnPaint(PaintEventArgs e)
        {
            //Added to prevent painting of "ok" button
            WinAPI.ShowDoneButton(this.Handle, false);
            base.OnPaint(e);
        }
        
        /// <summary>
        /// Handle paint event
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void insertAddress_Paint(object sender, System.Windows.Forms.PaintEventArgs e)
        {
            using (Graphics g = e.Graphics)
                using (Pen p = new Pen(Color.GreenYellow, 4))
                {
                    Rectangle r = new Rectangle(2, 2, insertAddress.Width-4, insertAddress.Height-4);
                    g.DrawRectangle(p, r);
                }
        }

        /// <summary>
        /// Handles the GotFocus event of the txtBoxDepAddress control.
        /// When the textBox for departure address gets focus,
        /// it shows a panel with the last inserted values
        /// for all fields
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void txtBoxDepAddress_GotFocus(object sender, EventArgs e)
        {
            controlSender = sender;
            city.Text = formStatus.DepartureFields.City;
            province.Text = formStatus.DepartureFields.Province;
            zipcode.Text = formStatus.DepartureFields.ZipCode;
            nation.Text = formStatus.DepartureFields.State;
            street.Text = formStatus.DepartureFields.Street;
            insertAddress.Visible = true;
        }

        /// <summary>
        /// Handles the GotFocus event of the txtBoxDesAddress control.
        /// When the textBox for destination address gets focus,
        /// it shows a panel with the last inserted values
        /// for all fields
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void txtBoxDesAddress_GotFocus(object sender, EventArgs e)
        {
            controlSender = sender;
            city.Text = formStatus.DestinationFields.City;
            province.Text = formStatus.DestinationFields.Province;
            zipcode.Text = formStatus.DestinationFields.ZipCode;
            nation.Text = formStatus.DestinationFields.State;
            street.Text = formStatus.DestinationFields.Street;
            insertAddress.Visible = true;
        }

        /// <summary>
        /// Handles the Click event of the tabTravel control.
        /// When the form is clicked,
        /// if there is an addressPanel visible,
        /// it disappears
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void tabTravel_Click(object sender, System.EventArgs e)
        {
            insertAddress.Visible = false;
        }
      
        #region Tab Paint
        /// <summary>
        /// Handle paint event for tabTravel
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void tabTravel_Paint(object sender, PaintEventArgs e)
        {
            using (Graphics g = e.Graphics)
            {
                Point[] p = new Point[]{
                    new Point(40,25), 
                    new Point(195,25), 
                    new Point(190,30), 
                    new Point(40,30)};
                using (Brush b = new SolidBrush(Color.Green))
                    g.FillPolygon(b, p);
                p[0].Y = p[1].Y = 30;
                p[2].Y = p[3].Y = 35;
                p[1].X -= 10;
                p[2].X -= 10;

                using (Brush b = new SolidBrush(Color.GreenYellow)) g.FillPolygon(b, p);

                g.DrawImage(Properties.Resources.circles, 8, 5);

                PrintDecorations(g, this.lblDpt.Left - 6, this.btnDepGPS.Right + 6, this.lblDpt.Top - 6, this.btnDestMap.Bottom + 6);
                PrintDecorations(g, this.lblDepDateTime.Left - 6, this.numSeats.Right + 6, this.lblDepDateTime.Top - 6, this.comboVehicle.Bottom + 9);

                using (Brush b = new SolidBrush(Color.FromArgb(48, 138, 13)))
                {
                    Rectangle r = new Rectangle(this.txtBoxDepAddress.Location.X - 3, this.txtBoxDepAddress.Location.Y - 3, this.txtBoxDepAddress.Width + 6, this.txtBoxDepAddress.Height + 6);
                    g.FillRectangle(b, r);
                    r.X = btnDepGPS.Location.X - 3; r.Y = btnDepGPS.Location.Y - 3; r.Width = btnDepGPS.Width + 6; r.Height = btnDepGPS.Height + 6;
                    g.FillRectangle(b, r);
                    r.X = btnDepMap.Location.X - 3; r.Y = btnDepMap.Location.Y - 3; r.Width = btnDepMap.Width + 6; r.Height = btnDepMap.Height + 6;
                    g.FillRectangle(b, r); 
                    r.X = depDateTime.Location.X - 3; r.Y = depDateTime.Location.Y - 3; r.Width = depDateTime.Width + 6; r.Height = depDateTime.Height + 6;
                    g.FillRectangle(b, r); 
                    r.X = numSeats.Location.X - 3; r.Y = numSeats.Location.Y - 3; r.Width = numSeats.Width + 6; r.Height = numSeats.Height + 6;
                    g.FillRectangle(b, r); 
                    r.X = txtBoxDesAddress.Location.X - 3; r.Y = txtBoxDesAddress.Location.Y - 3; r.Width = txtBoxDesAddress.Width + 6; r.Height = txtBoxDesAddress.Height + 6;
                    g.FillRectangle(b, r); 
                    r.X = btnDestGPS.Location.X - 3; r.Y = btnDestGPS.Location.Y - 3; r.Width = btnDestGPS.Width + 6; r.Height = btnDestGPS.Height + 6;
                    g.FillRectangle(b, r); 
                    r.X = btnDestMap.Location.X - 3; r.Y = btnDestMap.Location.Y - 3; r.Width = btnDestMap.Width + 6; r.Height = btnDestMap.Height + 6;
                    g.FillRectangle(b, r);
                    r.X = comboVehicle.Location.X - 3; r.Y = comboVehicle.Location.Y - 3; r.Width = comboVehicle.Width + 6; r.Height = comboVehicle.Height + 6;
                    g.FillRectangle(b, r);
                }
            }
        }

        /// <summary>
        /// Handle paint event for tabOptional
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void tabOptional_Paint(object sender, PaintEventArgs e)
        {
            using (Graphics g = e.Graphics)
            {
                Point[] p = new Point[]{
                    new Point(40,25), 
                    new Point(195,25), 
                    new Point(190,30), 
                    new Point(40,30)};
                using (Brush b = new SolidBrush(Color.Green))
                    g.FillPolygon(b, p);
                p[0].Y = p[1].Y = 30;
                p[2].Y = p[3].Y = 35;
                p[1].X -= 10;
                p[2].X -= 10;

                using (Brush b = new SolidBrush(Color.GreenYellow)) g.FillPolygon(b, p);

                g.DrawImage(Properties.Resources.circles, 8, 5);

                PrintDecorations(g, this.lblEstimatedTime.Left - 6, this.chkBoxLicensed.Right + 6, this.lblEstimatedTime.Top - 6, this.chkBoxLicensed.Bottom + 6);

                using (Brush b = new SolidBrush(Color.FromArgb(48, 138, 13)))
                {
                    Rectangle r = new Rectangle(this.destEstimatedTime.Location.X - 3, this.destEstimatedTime.Location.Y - 3, this.destEstimatedTime.Width + 6, this.destEstimatedTime.Height + 6);
                    g.FillRectangle(b, r);
                    r.X = txtBoxDeviation.Location.X - 3; r.Y = txtBoxDeviation.Location.Y - 3; r.Width = txtBoxDeviation.Width + 6; r.Height = txtBoxDeviation.Height + 6;
                    g.FillRectangle(b, r);
                    r.X = txtBoxEstimatedBudget.Location.X - 3; r.Y = txtBoxEstimatedBudget.Location.Y - 3; r.Width = txtBoxEstimatedBudget.Width + 6; r.Height = txtBoxEstimatedBudget.Height + 6;
                    g.FillRectangle(b, r);
                    r.X = txtBoxNote.Location.X - 3; r.Y = txtBoxNote.Location.Y - 3; r.Width = txtBoxNote.Width + 6; r.Height = txtBoxNote.Height + 6;
                    g.FillRectangle(b, r);
                }
            }
        }

        private void PrintDecorations(Graphics g, int left, int right, int top, int bottom)
        {
            int roundDiameter = 10;
            Rectangle r = new Rectangle(left, top, roundDiameter, roundDiameter);
            using (Brush b = new SolidBrush(Color.FromArgb(222, 241, 126)))
            {
                g.FillEllipse(b, r);
                r.X = right - roundDiameter - 1;
                g.FillEllipse(b, r);
                r.Y = bottom - roundDiameter - 1;
                g.FillEllipse(b, r);
                r.X = left;
                g.FillEllipse(b, r);
                r.X = left + roundDiameter / 2; r.Y = top; r.Width = right - left - roundDiameter; r.Height = bottom - top;
                g.FillRectangle(b, r);
                r.X = left; r.Y = top + roundDiameter / 2; r.Width = roundDiameter / 2; r.Height = bottom - top - roundDiameter;
                g.FillRectangle(b, r);
                r.X = right - roundDiameter / 2;
                g.FillRectangle(b, r);
            }
        }
        
        #endregion;

        #region Map Handlers
        /// <summary>
        /// Allows to insert a departure address taking location from a map
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void btnDepMap_Click(object sender, EventArgs e)
        {
            MapSelection map;
            if (this.txtBoxDepAddress.Text.Equals("")) map = new MapSelection();
            else
            {
                String[] temp = this.txtBoxDepAddress.Text.Split(',');
                try
                {
                    map = new MapSelection(Convert.ToDouble(temp[0]), Convert.ToDouble(temp[1]));
                }
                catch (FormatException)
                {
                    map = new MapSelection();
                }
            }
            Welcome.formBuffer.Add(map, ResourceManager.Instance.GetString("MapSelection"));
            map.ShowDialog();
            
            if (map.AddressAcquired)
            {
                formStatus.setDepLatLong(map.Latitude, map.Longitude);

                menuRight.Enabled = false;

                Welcome.rrp.SendReverseGeoCodingRequest(
                    this,
                    rrp_DepGeocodeResponse,
                    new TripLOAMobile.WS_GeoRef.GeoPoint() { Lat = formStatus.LatDep, Lng = formStatus.LongDep });
            }

            map.Dispose();
        }

        /// <summary>
        /// Allows to insert a destination address taking location from a map
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void btnDestMap_Click(object sender, EventArgs e)
        {
            MapSelection map;
            if (this.txtBoxDesAddress.Text.Equals("")) map = new MapSelection();
            else
            {
                String[] temp = this.txtBoxDesAddress.Text.Split(',');
                try
                {
                    map = new MapSelection(Convert.ToDouble(temp[0]), Convert.ToDouble(temp[1]));
                }
                catch (FormatException)
                {
                    map = new MapSelection();
                }
            }
            Welcome.formBuffer.Add(map, ResourceManager.Instance.GetString("MapSelection"));
            map.ShowDialog();
            
            if (map.AddressAcquired)
            {
                formStatus.setDesLatLong(map.Latitude, map.Longitude);

                menuRight.Enabled = false;

                Welcome.rrp.SendReverseGeoCodingRequest(
                    this,
                    rrp_DestGeocodeResponse,
                    new TripLOAMobile.WS_GeoRef.GeoPoint() { Lat = formStatus.LatDes, Lng = formStatus.LongDes });
            }

            map.Dispose();
        }
  
        #endregion;

        #region GPS Event Handlers

        delegate void updatePosition();

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="args"></param>
        public void gps_DepLocationChanged(object sender, GPS.LocationChangedEventArgs args)
        {
            Welcome.gps.Position = args.Position;
            if (first)
            {
                first = false;
                MessageBox.Show(ResourceManager.Instance.GetString("gpsAvailable"), ResourceManager.Instance.GetString("gpsCaption"), 
                    MessageBoxButtons.OK, MessageBoxIcon.Question, MessageBoxDefaultButton.Button2);
                updatePosition p = new updatePosition(updateDepPosition);
                this.Invoke(p);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="args"></param>
        public void gps_DepDeviceStateChanged(object sender, GPS.DeviceStateChangedEventArgs args)
        {
            Welcome.gps.DeviceState = args.DeviceState;
            if (first)
            {
                first = false;
                DialogResult result = MessageBox.Show(ResourceManager.Instance.GetString("gpsAvailable"),
                    ResourceManager.Instance.GetString("gpsCaption"), MessageBoxButtons.OK, MessageBoxIcon.Question, MessageBoxDefaultButton.Button2);
                updatePosition p = new updatePosition(updateDepPosition);
                this.Invoke(p);
            }
        }

        public void gps_DestLocationChanged(object sender, GPS.LocationChangedEventArgs args)
        {
            Welcome.gps.Position = args.Position;
            if (first)
            {
                first = false;
                DialogResult result = MessageBox.Show(ResourceManager.Instance.GetString("gpsAvailable"),
                    ResourceManager.Instance.GetString("gpsCaption"), MessageBoxButtons.OK, MessageBoxIcon.Question, MessageBoxDefaultButton.Button2);
                updatePosition p = new updatePosition(updateDestPosition);
                this.Invoke(p);
            }
        }

        public void gps_DestDeviceStateChanged(object sender, GPS.DeviceStateChangedEventArgs args)
        {
            Welcome.gps.DeviceState = args.DeviceState;
            if (first)
            {
                first = false;
                MessageBox.Show(ResourceManager.Instance.GetString("gpsAvailable"),
                    ResourceManager.Instance.GetString("gpsCaption"), MessageBoxButtons.OK, MessageBoxIcon.Question, MessageBoxDefaultButton.Button2);
                updatePosition p = new updatePosition(updateDestPosition);
                this.Invoke(p);
            }
        }

        private void updateDepPosition()
        {
            formStatus.setDepLatLong(Welcome.gps.Position.Latitude, Welcome.gps.Position.Longitude);

            menuRight.Enabled = false;

            Welcome.rrp.SendReverseGeoCodingRequest(
                this,
                rrp_DepGeocodeResponse,
                new TripLOAMobile.WS_GeoRef.GeoPoint() { Lat = Welcome.gps.Position.Latitude, Lng = Welcome.gps.Position.Longitude });
        }

        private void updateDestPosition()
        {
            formStatus.setDesLatLong(Welcome.gps.Position.Latitude, Welcome.gps.Position.Longitude);

            menuRight.Enabled = false;

            Welcome.rrp.SendReverseGeoCodingRequest(
                this,
                rrp_DestGeocodeResponse,
                new TripLOAMobile.WS_GeoRef.GeoPoint() { Lat = Welcome.gps.Position.Latitude, Lng = Welcome.gps.Position.Longitude });
        }
        #endregion

        #region GPS Handlers
        private void btnDepGPS_Click(object sender, EventArgs e)
        {
            if (!Welcome.gps.Opened)
            {
                DialogResult result = MessageBox.Show(ResourceManager.Instance.GetString("wantGpsOn"),
                    ResourceManager.Instance.GetString("gpsCaption"), MessageBoxButtons.YesNo, MessageBoxIcon.Question, MessageBoxDefaultButton.Button2);
                if (result == System.Windows.Forms.DialogResult.Yes)
                {
                    Welcome.gps.Open();
                    gpsDepEvent = true;
                    first = true;
                    Welcome.gps.DeviceStateChanged += new GPS.Gps.DeviceStateChangedEventHandler(gps_DepDeviceStateChanged);
                    Welcome.gps.LocationChanged += new GPS.Gps.LocationChangedEventHandler(gps_DepLocationChanged);
                }
            }
            else
            {
                try
                {
                    if (Welcome.gps.Position.LatitudeValid && Welcome.gps.Position.LongitudeValid)
                    {
                        formStatus.setDepLatLong(Welcome.gps.Position.Latitude, Welcome.gps.Position.Longitude);

                        menuRight.Enabled = false;

                        Welcome.rrp.SendReverseGeoCodingRequest(
                            this,
                            rrp_DepGeocodeResponse,
                            new TripLOAMobile.WS_GeoRef.GeoPoint() { Lat = Welcome.gps.Position.Latitude, Lng = Welcome.gps.Position.Longitude });
                    }
                    else
                    {
                        MessageBox.Show(ResourceManager.Instance.GetString("gpsNotAvailable"),
                                    ResourceManager.Instance.GetString("gpsCaption"),
                                    MessageBoxButtons.OK, MessageBoxIcon.Asterisk, MessageBoxDefaultButton.Button2);
                    }
                }
                catch (NullReferenceException)
                {
                    MessageBox.Show(ResourceManager.Instance.GetString("gpsNotAvailable"),
                                ResourceManager.Instance.GetString("gpsCaption"),
                                MessageBoxButtons.OK, MessageBoxIcon.Asterisk, MessageBoxDefaultButton.Button2);
                }
            }
        }

        private void btnDestGPS_Click(object sender, EventArgs e)
        {
            if (!Welcome.gps.Opened)
            {
                DialogResult result = MessageBox.Show(ResourceManager.Instance.GetString("wantGpsOn"),
                    ResourceManager.Instance.GetString("gpsCaption"), MessageBoxButtons.YesNo, MessageBoxIcon.Question, MessageBoxDefaultButton.Button2);
                if (result == System.Windows.Forms.DialogResult.Yes)
                {
                    Welcome.gps.Open();
                    gpsDestEvent = true;
                    first = true;
                    Welcome.gps.DeviceStateChanged += new GPS.Gps.DeviceStateChangedEventHandler(gps_DestDeviceStateChanged);
                    Welcome.gps.LocationChanged += new GPS.Gps.LocationChangedEventHandler(gps_DestLocationChanged);
                }
            }
            else
            {
                try
                {
                    if (Welcome.gps.Position.LatitudeValid && Welcome.gps.Position.LongitudeValid)
                    {
                        formStatus.setDesLatLong(Welcome.gps.Position.Latitude, Welcome.gps.Position.Longitude);

                        menuRight.Enabled = false;
                        
                        Welcome.rrp.SendReverseGeoCodingRequest(
                            this,
                            rrp_DestGeocodeResponse,
                            new TripLOAMobile.WS_GeoRef.GeoPoint() { Lat = Welcome.gps.Position.Latitude, Lng = Welcome.gps.Position.Longitude });
                    }
                    else
                    {
                        MessageBox.Show(ResourceManager.Instance.GetString("gpsNotAvailable"),
                                    ResourceManager.Instance.GetString("gpsCaption"),
                                    MessageBoxButtons.OK, MessageBoxIcon.Asterisk, MessageBoxDefaultButton.Button2);
                    }
                }
                catch (NullReferenceException)
                {
                    MessageBox.Show(ResourceManager.Instance.GetString("gpsNotAvailable"),
                                ResourceManager.Instance.GetString("gpsCaption"),
                                MessageBoxButtons.OK, MessageBoxIcon.Asterisk, MessageBoxDefaultButton.Button2);
                }
            }
        }
        #endregion

        #region GeoCodeResponseHandling
        void rrp_DepGeocodeResponse(RemoteResourceProvider.GeoCodeResponseEventArgs e)
        {
            if (e.Status == RemoteResourceProvider.okStatus)
            {
                formStatus.DepartureFields.City = e.Address.getCityRGeoCoded();
                formStatus.DepartureFields.Province = e.Address.getProvinceRGeoCoded();
                formStatus.DepartureFields.ZipCode = e.Address.getZipCodeRGeoCoded();
                formStatus.DepartureFields.State = e.Address.getStateRGeoCoded();
                formStatus.DepartureFields.Street = e.Address.getStreetRGeoCoded();
                txtBoxDepAddress.Text = formStatus.DepartureFields.getReadableString();
            }
            else MessageBox.Show(e.Status);
            menuRight.Enabled = true;
        }

        void rrp_DestGeocodeResponse(RemoteResourceProvider.GeoCodeResponseEventArgs e)
        {
            if (e.Status == RemoteResourceProvider.okStatus)
            {
                formStatus.DestinationFields.City = e.Address.getCityRGeoCoded();
                formStatus.DestinationFields.Province = e.Address.getProvinceRGeoCoded();
                formStatus.DestinationFields.ZipCode = e.Address.getZipCodeRGeoCoded();
                formStatus.DestinationFields.State = e.Address.getStateRGeoCoded();
                formStatus.DestinationFields.Street = e.Address.getStreetRGeoCoded();
                txtBoxDesAddress.Text = formStatus.DestinationFields.getReadableString();
            }
            else MessageBox.Show(e.Status);
            menuRight.Enabled = true;
        }
        #endregion

        /// <summary>
        /// Handles the Click event of the btnCancel control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void btnCancel_Click(object sender, EventArgs e)
        {
            foreach (Control txtBox in insertAddress.Controls)
                if (txtBox is TextBox)
                    txtBox.Text = "";
            insertAddress.Visible = false;
        }

        /// <summary>
        /// Inserts the new values for the address
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void btnOk_Click(object sender, EventArgs e)
        {   
            AddressFields actualFields;
            bool dep = true, addressModified = false;
            TextBox control = (TextBox)controlSender;
            if (control.Name == "txtBoxDepAddress")
                actualFields = formStatus.DepartureFields;
            else
            {
                actualFields = formStatus.DestinationFields;
                dep = false;
            }

            if (actualFields.City != city.Text)
            {
                actualFields.City = city.Text;
                addressModified = true;
            }
            if (actualFields.State != nation.Text)
            {
                actualFields.State = nation.Text;
                addressModified = true;
            }
            if (actualFields.Street != street.Text)
            {
                actualFields.Street = street.Text;
                addressModified = true;
            }
            if (actualFields.Province != province.Text)
            {
                actualFields.Province = province.Text;
                addressModified = true;
            }
            if (actualFields.ZipCode != zipcode.Text)
            {
                actualFields.ZipCode = zipcode.Text;
                addressModified = true;
            }
            if (addressModified)
            {
                control.Text = actualFields.getReadableString();
                if (dep)
                    formStatus.setDepLatLongNOTDefined();
                else
                    formStatus.setDesLatLongNOTDefined();
            }


            insertAddress.Visible = false;
        }

        /// <summary>
        /// Prepares all the informations needed to make the remote request.
        /// </summary>
        private void prepareRemoteRequest()
        {
            this.startAnimation();

            formStatus.DepartureTime = depDateTime.Value;
            formStatus.Smoker = chkBoxSmoker.Checked;
            formStatus.Comment = txtBoxNote.Text;
            formStatus.FreeSeats = Convert.ToByte(numSeats.Value);

            if((this.txtBoxDeviation.Text!=null)&&(this.txtBoxDeviation.Text!=""))
                formStatus.MaxDeviation = Convert.ToSingle(this.txtBoxDeviation.Text);
            if ((this.txtBoxEstimatedBudget.Text != null) && (this.txtBoxEstimatedBudget.Text != ""))
                formStatus.EstimatedBudget = Convert.ToDecimal(this.txtBoxEstimatedBudget.Text);
            if (this.destEstimatedTime.Value.Minute != 0)
                formStatus.EstimatedTime = this.destEstimatedTime.Value.getHoursAndMinutesInMinutes();
            formStatus.LicenseRequired = this.chkBoxLicensed.Checked;

            #region vehicle
            formStatus.Veichle = listOfVehicles[comboVehicle.SelectedIndex].VehicleClass;
            formStatus.VehicleID = listOfVehicles[comboVehicle.SelectedIndex].Id;
            #endregion
        }

        /// <summary>
        /// Allows to publish the travel created
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void publishMenuItem_Click(object sender, EventArgs e)
        {
            this.prepareRemoteRequest();
            formStatus.Draft = false;
            Welcome.rrp.SendInsertTravelRequest(this, new RemoteResourceProvider.InsertTravelResponseHandler(rrp_InsertTravelRensponse), formStatus);
        }

        /// <summary>
        /// Allows to save as draft the created travel
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void draftMenuItem_Click(object sender, EventArgs e)
        {
            this.prepareRemoteRequest();
            formStatus.Draft = true;
            Welcome.rrp.SendInsertTravelRequest(this, new RemoteResourceProvider.InsertTravelResponseHandler(rrp_InsertTravelRensponse), formStatus);
        }

        #region SIP handling
        private object focused; //Which editable control was last focused
        private int delta; //variation from the original location due to keyboard visualization

        /// <summary>
        /// Shows a keyboard when an editable control (address fields) gets focus
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void editableControl_GotFocus(object sender, EventArgs e)
        {
            //Shows the INPUT_PANEL
            focused = sender; 
            if(sender != depDateTime && sender != numSeats && sender != this.destEstimatedTime)
                sip.Enabled = true;
        }

        /// <summary>
        /// Hides the keyboard when an editable control losts focus
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void editableControl_LostFocus(object sender, EventArgs e)
        {
            //Hides the INPUT_PANEL
            sip.Enabled = false;
        }

        /// <summary>
        /// When the keyboard is enabled/disabled
        /// the screen must be reset
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void sip_EnabledChanged(object sender, EventArgs e)
        {
            if (focused == txtBoxNote)
                txtBoxNote.Height = ((sip.Enabled) ? sip.VisibleDesktop.Height - 3 : chkBoxLicensed.Top - 6) - txtBoxNote.Top;

            else if (focused == depDateTime || focused == numSeats)
            {
                if (sip.Enabled)
                {
                    lblDest.Top = lblDpt.Top;
                    txtBoxDesAddress.Top = txtBoxDepAddress.Top;
                    btnDestGPS.Top = btnDepGPS.Top;
                    btnDestMap.Top = btnDepMap.Top;

                    lblDepDateTime.Top -= delta;
                    depDateTime.Top -= delta;
                    lblSeats.Top -= delta;
                    numSeats.Top -= delta;
                    lblVehicle.Top -= delta;
                    comboVehicle.Top -= delta;
                }
                else
                {
                    lblDest.Top += delta;
                    txtBoxDesAddress.Top += delta;
                    btnDestGPS.Top += delta;
                    btnDestMap.Top += delta;

                    lblDepDateTime.Top += delta;
                    depDateTime.Top += delta;
                    lblSeats.Top += delta;
                    numSeats.Top += delta;
                    lblVehicle.Top += delta;
                    comboVehicle.Top += delta;
                }
                this.tabTravel.Invalidate();
                this.tabTravel.Update();
            }
        }
        #endregion
    }
}